package com.hxc.shop.service;

import com.alibaba.fastjson.JSON;
import com.hxc.shop.bean.ShopImage;
import com.hxc.shop.common.ResultCode;
import com.hxc.shop.common.ResultVO;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import com.hxc.shop.mapper.Mysql.FileMapper;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;

@Slf4j
@Service
public class FileService {

  private static String host = "47.92.53.108";
  private static String user = "ftpAdmin";
  private static String passWord = "ftpAdmin";
  private static Integer port = 21;

  @Resource
  private FileMapper fileMapper;


  public ResultVO loadLocalFile(MultipartFile file,String path) throws Exception {
    //path范例:E:\file
    System.out.println("文件:"+path);
    String fileName = file.getOriginalFilename();
    File file1 = new File(path+"\\"+fileName);
    if (!file1.exists()) {
      file1.mkdirs();
    }
    try {
      file.transferTo(file1);
    }catch (Exception e) {
      e.printStackTrace();
      log.error("本地上传文件失败:"+e.getMessage());
      return new ResultVO(ResultCode.ERROR.getCode(),"上传本地文件失败:"+path+"\\"+fileName+"=="+e.getMessage());
    }
    return new ResultVO(ResultCode.SUCCESS.getCode(),"上传文件成功:"+path+"\\"+fileName);
  }
  // ftp上传下载
  public ResultVO FtpUpload(MultipartFile file,String path) throws Exception{
    String fileName = file.getOriginalFilename();
    InputStream inputStream = file.getInputStream();

    return new ResultVO(upload(path,fileName,inputStream));
  }



  public static ResultVO upload(String targetPath,String fileName, InputStream inputStream) throws IOException {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    //实例化ftpClient
    FTPClient ftpClient = new FTPClient();
    //设置登陆超时时间,默认是20s
    ftpClient.setDataTimeout(12000);
    //1.连接服务器
    ftpClient.connect(host,port);
    //2.登录（指定用户名和密码）
    boolean b = ftpClient.login(user,passWord);
    if(!b) {
      if (ftpClient.isConnected()) {
        // 断开连接
        ftpClient.disconnect();
      }
      log.error("连接ftp失败:登录超时");
      return new ResultVO(ResultCode.ERROR.getCode(),"登陸超时");
    }
    // 设置字符编码
    ftpClient.setControlEncoding("UTF-8");
    //基本路径，一定存在
//    String basePath="/";
    // 部署服务器放开
    String basePath="/www/server/tomcat/webapps/IMG/";
    String[] pathArray = targetPath.split("/");
    for(String path:pathArray){
      basePath+=path+"/";
      //3.指定目录 返回布尔类型 true表示该目录存在
      boolean dirExsists = ftpClient.changeWorkingDirectory(basePath);
      //4.如果指定的目录不存在，则创建目录
      if(!dirExsists){
        //此方式，每次，只能创建一级目录
        boolean flag=ftpClient.makeDirectory(basePath);
        if (flag){
          log.info(sdf.format(new Date())+"上传文件到ftp创建目录成功:"+basePath);
        }
      }
    }
    //重新指定上传文件的路径
    ftpClient.changeWorkingDirectory(targetPath);
    //5.设置上传文件的方式
    ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
    /**
     * 6.执行上传
     * remote 上传服务后，文件的名称
     * local 文件输入流
     * 上传文件时，如果已经存在同名文件，会被覆盖
     */
    boolean uploadFlag = ftpClient.storeFile(fileName,inputStream);
    if(uploadFlag)
      log.info("上传文件成功:文件名-"+fileName);
    return new ResultVO(ResultCode.SUCCESS.getCode(),"上传成功!",fileName);
  }

  // ftp读取文件
  public ResultVO FtpReadImageList(String ftpDirPath) throws IOException {
    FTPClient ftp = new FTPClient();
    // 服务器读取基础路径
    String basePath="/www/server/tomcat/webapps/IMG/";
    if (!StringUtils.isEmpty(ftpDirPath)) {
      ftpDirPath=basePath+ftpDirPath;
    }else {
      ftpDirPath = basePath;
    }
    ftp.setDataTimeout(12000);
    ftp.connect(host,port);
    boolean b = ftp.login(user,passWord);
    if(!b) {
      if (ftp.isConnected()) {
        // 断开连接
        ftp.disconnect();
      }
      System.out.println("登陸超時");
      return new ResultVO(ResultCode.ERROR.getCode(),"登陸超时");
    }
    // 接收图片名称列表
    List<String> ImageNameList = new ArrayList();
    // 接收路径列表
    List<String> pathList = new ArrayList<>();
    try {
      // 通过提供的文件路径获取FTPFile对象列表
      FTPFile[] files = ftp.listFiles(ftpDirPath);
      log.info("路径:"+ftpDirPath+"读取文件列表为:"+files);
      // 遍历文件列表，打印出文件名称
      for (int i = 0; i < files.length; i++) {
        FTPFile ftpFile = files[i];
        // 此处只打印文件，未遍历子目录（如果需要遍历，加上递归逻辑即可）
        if (ftpFile.isFile()) {
          ImageNameList.add("文件:"+ftpFile.getName());
        } else {
          if (!ftpFile.getName().equals(".")&& !ftpFile.getName().equals("..")) {
            ImageNameList.add("文件夹:"+ftpFile.getName());
          }
        }
      }
    } catch (IOException e) {
      return new ResultVO(ResultCode.ERROR.getCode(),e.getMessage());
    }
    System.out.println("文件夹列表:"+pathList);
    return new ResultVO(ResultCode.SUCCESS.getCode(),"读取图片列表成功!",ImageNameList);
  }


  public ResultVO uploadImageToServer(MultipartFile file) {
//    String path = "http://47.92.53.108:8080/IMG";
    String path = "http://127.0.0.1:8080/IMG";
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//为上传到服务器的文件取名，使用UUID防止文件名重复
    String filename= file.getOriginalFilename();

    // 查找是否有该图片上传
    String iamgeInfo = fileMapper.findImageByPath(path +"/" + filename);

    if (!StringUtils.isEmpty(iamgeInfo)) {
      return new ResultVO(ResultCode.ERROR.getCode(),"该图片名已占用，请更换图片名称:"+filename);
    }

    try{
//使用Jersey客户端上传文件
      Client client = Client.create();
      WebResource webResource = client.resource(path +"/" + filename);
      client.resource(path);
      webResource.put(file.getBytes());
    }catch(Exception ex){
      return new ResultVO(ResultCode.ERROR.getCode(),"上传图片失败:"+path+"/"+filename+ ex.getMessage());
    }
    ShopImage shopImage = new ShopImage();
    shopImage.setCreateTime(sdf.format(new Date()));
    shopImage.setImagePath(path +"/" + filename);
    try{
      fileMapper.InsertImage(shopImage);
    }catch (Exception e) {
      Client client = Client.create();
      WebResource webResource = client.resource(path +"/" + filename);
      client.resource(path);
      webResource.delete();
      return new ResultVO(ResultCode.ERROR.getCode(),"新增图片数据失败，已从服务器移除该图片:"+e.getMessage());
    }
    return new ResultVO(ResultCode.SUCCESS.getCode(),"上传文件成功:"+path+"/"+filename);
  }

  public ResultVO uploadImageToServerV2(MultipartFile file){
    String path = "http://47.92.53.108:8080/IMG";
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    //为上传到服务器的文件取名，使用UUID防止文件名重复
    String type= file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
    String filename= UUID.randomUUID().toString()+type;
    try{

      Client client = Client.create();
      WebResource webResource = client.resource(path +"/" + URLEncoder.encode(filename,"utf-8"));
      webResource.put(file.getBytes());
      System.out.println("上传成功");
      System.out.println("图片路径==》"+path+filename);
    }catch(Exception ex){
      return new ResultVO(ResultCode.ERROR.getCode(),"上传图片失败:"+path+"/"+filename+ ex.getMessage());
    }
    ShopImage shopImage = new ShopImage();
    shopImage.setCreateTime(sdf.format(new Date()));
    shopImage.setImagePath(path +"/" + filename);
    try{
      fileMapper.InsertImage(shopImage);
    }catch (Exception e) {
      Client client = Client.create();
      WebResource webResource = client.resource(path +"/" + filename);
      client.resource(path);
      webResource.delete();
      return new ResultVO(ResultCode.ERROR.getCode(),"新增图片数据失败，已从服务器移除该图片:"+e.getMessage());
    }
    return new ResultVO(ResultCode.SUCCESS.getCode(),"上传文件成功:"+path+"/"+filename);
  }

  public ResultVO deleteImageFromServer(String path) {
    String imagePath = fileMapper.findImageByPath(path);
    if (StringUtils.isEmpty(imagePath)) {
      return new ResultVO(ResultCode.ERROR.getCode(),"服务器无该文件!删除失败!");
    }

    try{
      fileMapper.deleteIamgeByPath(path);
      Client client = Client.create();
      WebResource webResource = client.resource(path);
      client.resource(path);
      webResource.delete();
    }catch (Exception e){
      return new ResultVO(ResultCode.ERROR.getCode(),"删除图片失败:"+e.getMessage());
    }
    return new ResultVO(ResultCode.SUCCESS.getCode(),"删除服务器文件成功:"+path);
  }

  public ResultVO getAllImageFromServer() {
    List<ShopImage> shopImageList = new ArrayList<>();
    try {
      shopImageList = fileMapper.getAllServerImage();
    }catch (Exception e){
      return new ResultVO(ResultCode.ERROR.getCode(),"获取图片数据失败:"+e.getMessage());
    }
    return new ResultVO(ResultCode.SUCCESS.getCode(),"获取图片数据成功!",shopImageList);
  }

  public ResultVO getImageByteById(Integer id) {
    try {
      ShopImage shopImage = fileMapper.getImageByteById(id);
      if (shopImage == null) {
        throw new Exception("未查找到对应的图片编号:"+id);
      }
      return new ResultVO(ResultCode.SUCCESS,shopImage);

    }catch (Exception e) {
      return new ResultVO(ResultCode.ERROR.getCode(),"获取图片失败:"+e.getMessage());
    }
  }

  public ResponseEntity<byte[]> getImageFileById(Integer id) {
    HttpHeaders httpHeaders=new HttpHeaders();
    try {
      ShopImage shopImage = fileMapper.getImageByteById(id);
      if (shopImage ==null) {
        return new ResponseEntity<>(null, httpHeaders, HttpStatus.NOT_FOUND);
      }
      if (shopImage.getImageByte() ==null) {
        return new ResponseEntity<>(null,httpHeaders,HttpStatus.NOT_FOUND);
      }
      byte[] data= shopImage.getImageByte();
      httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
      httpHeaders.setContentDisposition(ContentDisposition.builder("file").filename(shopImage.getImageName(), StandardCharsets.UTF_8).build());
      return new ResponseEntity<>(data, httpHeaders, HttpStatus.OK);
    }catch (Exception e) {
      return new ResponseEntity<>(null, httpHeaders, HttpStatus.NOT_FOUND);
    }
  }

  // 根据文件转字节流
  public ResultVO uploadFileToBytes(MultipartFile file) {
   try {
     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     InputStream inputStream = file.getInputStream();
     String fileName = file.getOriginalFilename();
     BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
     byte[] buffer;
     int len;
     byte[] buf = new byte[2048];
     while ((len = bufferedInputStream.read(buf)) != -1) {
       byteArrayOutputStream.write(buf,0,len);
     }
     byteArrayOutputStream.flush();
     buffer = byteArrayOutputStream.toByteArray();

     ShopImage shopImage = new ShopImage();
     shopImage.setImagePath("");
     shopImage.setImageByte(buffer);
     shopImage.setImageName(fileName);
     shopImage.setCreateTime(sdf.format(new Date()));
     fileMapper.InsertImage(shopImage);

     System.out.println(JSON.toJSONString(shopImage));
     inputStream.close();
     bufferedInputStream.close();
     byteArrayOutputStream.close();
     return new ResultVO(ResultCode.SUCCESS.getCode(),"保存图片成功!",shopImage.getId());
   } catch (Exception e) {
     return new ResultVO(ResultCode.ERROR.getCode(),"保存文件失败:",e.getMessage());
   }
  }

}
